import os
from PIL import Image

from django.conf import settings
from django.contrib import messages
from django.contrib.auth import login as login_user, logout as logout_user
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import SetPasswordForm
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.db import transaction
from django.shortcuts import render, redirect, get_object_or_404
from django.template.loader import render_to_string

from .forms import LoginForm, RegistrationForm, ResetForm, ProfileForm, ChangePasswordForm
from .models import ConfirmationKey, Profile
from ..decorators import canonical


@canonical(Profile)
def profile(request, profile):
    """
    用户主页
    """
    return render(request, 'accounts/profile.html', {
        'profile': profile,
    })


def login(request):
    """
    用户登录
    """
    if request.method == 'POST':
        form = LoginForm(data=request.POST)
        if form.is_valid():
            if not form.cleaned_data.get('remember_me'):
                request.session.set_expiry(0)
            
            login_user(request, form.get_user())
            return redirect(request.GET['next'] if 'next' in request.GET else 'translations:index')
    else:
        form = LoginForm()
    return render(request, 'accounts/login.html', {
        'form': form,
    })


@login_required
def logout(request):
    """
    用户退出
    """
    logout_user(request)
    messages.info(request, "您已成功退出")
    return redirect('translations:index')


@transaction.atomic
def register(request):
    """
    新用户注册
    """
    if request.method == 'POST':
        form = RegistrationForm(data=request.POST)
        if form.is_valid():
            user = form.save(commit=False)
            user.email = form.cleaned_data['email']
            user.is_active = False
            user.save()
            key = ConfirmationKey(user=user)
            key.save()
            template = render_to_string('accounts/emails/register.txt', {
                'user': user,
                'url': request.build_absolute_uri(reverse('accounts:register_confirm', kwargs={'key': key.key})),
            })
            send_mail('2buntu Registration', template, '2buntu <%s>' % settings.EMAIL_HOST_USER, [user.email])
            messages.info(request, "系统已向您的邮箱发送了一封认证邮件，请点击邮件中的链接完成注册！")
            return redirect('translations:index')
    else:
        form = RegistrationForm()
    return render(request, 'accounts/register.html', {
        'form': form,
    })


@transaction.atomic
def register_confirm(request, key):
    """
    认证帐号

    参数 key: 唯一识别码
    """
    key = get_object_or_404(ConfirmationKey, key=key)
    key.user.is_active = True
    key.user.save()
    key.delete()
    messages.info(request, "恭喜您，帐号注册成功！现在可以登录了")
    return redirect('accounts:login')


def reset(request):
    """
    通过邮箱重置密码
    """
    if request.method == 'POST':
        form = ResetForm(data=request.POST)
        if form.is_valid():
            key = ConfirmationKey(user=form.user)
            key.save()
            template = render_to_string('accounts/emails/reset.txt', {
                'user': key.user,
                'url': request.build_absolute_uri(reverse('accounts:reset_confirm', kwargs={'key': key.key})),
            })
            send_mail('2buntu Password Reset', template, '2buntu <%s>' % settings.EMAIL_HOST_USER, [key.user.email])
            messages.info(request, "密码重置链接已经发送到您的邮件中，请查收")
            return redirect('translations:index')
    else:
        form = ResetForm()
    return render(request, 'accounts/reset.html', {
        'form': form,
    })


@transaction.atomic
def reset_confirm(request, key):
    """
    完成密码重置过程
    """
    key = get_object_or_404(ConfirmationKey, key=key)
    if request.method == 'POST':
        form = SetPasswordForm(user=key.user, data=request.POST)
        if form.is_valid():
            form.save()
            key.delete()
            messages.info(request, "恭喜您，密码重置成功！现在可以登录了")
            return redirect('accounts:login')
    else:
        form = SetPasswordForm(user=key.user)
    return render(request, 'accounts/reset_confirm.html', {
        'form': form,
        'key': key.key,
    })


@login_required
@transaction.atomic
def setting(request, id):
    """
    编辑用户资料
    """
    profile = get_object_or_404(Profile, user=id)
    if request.method == 'POST':
        form = ProfileForm(instance=profile, data=request.POST)
        if form.is_valid():
            profile.user.email = form.cleaned_data['email']
            profile.user.save()
            form.save()
            return redirect(profile)
    else:
        form = ProfileForm(
            instance=profile,
            initial={
                'email': profile.user.email,
            })
    return render(request, "accounts/setting.html", {
        'form': form,
        'profile': profile,
    })


@login_required
def password(request):
    """
    更改密码
    """
    user = request.user
    if request.method == 'POST':
        form = ChangePasswordForm(request.POST)
        if form.is_valid():
            new_password = form.cleaned_data.get('new_password')
            user.set_password(new_password)
            user.save()
            messages.info(request, "您的密码已更改！")
    else:
        form = ChangePasswordForm(instance=user)
    return render(request, 'accounts/password.html', {'form':form})


@login_required
def avatar(request):
    """
    更改头像
    """
    uploaded_avatar = False
    try:
        if request.GET.get('upload_avatar') == 'uploaded':
            uploaded_avatar = True
    except Exception:
        pass
    return render(request, 'accounts/avatar.html', {'uploaded_avatar': uploaded_avatar})


@login_required
def upload_avatar(request):
    """
    上传头像
    """
    try:
        user = request.user
        profile_avatars = settings.MEDIA_ROOT + '/avatars/{year}/{month}/{day}/'.format(
            year = user.date_joined.year,
            month = user.date_joined.month,
            day = user.date_joined.day)
        if not os.path.exists(profile_avatars):
            os.makedirs(profile_avatars)
        f = request.FILES['avatar']
        filename = profile_avatars + request.user.username + '_tmp.jpg'
        with open(filename, 'wb+') as destination:
            for chunk in f.chunks():
                destination.write(chunk)
        im = Image.open(filename)
        width, height = im.size
        if width > 350:
            new_width = 350
            new_height = (height * 350) / width
            new_size = new_width, new_height
            im.thumbnail(new_size, Image.ANTIALIAS)
            im.save(filename)
        return redirect('%s?upload_avatar=uploaded' % reverse('accounts:avatar'))
    except Exception:
        return redirect('accounts:avatar')


@login_required
def save_uploaded_avatar(request):
    """
    保存头像
    """
    try:
        x = int(request.POST.get('x'))
        y = int(request.POST.get('y'))
        w = int(request.POST.get('w'))
        h = int(request.POST.get('h'))
        user = request.user
        profile_avatars = settings.MEDIA_ROOT + '/avatars/{year}/{month}/{day}/'.format(
            year = user.date_joined.year,
            month = user.date_joined.month,
            day = user.date_joined.day)
        tmp_filename = profile_avatars + user.username + '_tmp.jpg'
        filename = profile_avatars + user.username + '.jpg'
        im = Image.open(tmp_filename)
        cropped_im = im.crop((x, y, w+x, h+y))
        cropped_im.thumbnail((200, 200), Image.ANTIALIAS)
        cropped_im.save(filename)
        os.remove(tmp_filename)
    except Exception:
        pass
    return redirect('accounts:avatar')
